package org.smile.bootstrap;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

public class BootstrapClassLoader extends URLClassLoader {

    private Map<String, URL> resources = new HashMap<>();

    public BootstrapClassLoader(ClassLoader parent) {
        super(new URL[0], parent);
    }

    /**
     * 把一个目录做为jar的库
     *
     * @param lib
     * @param parent
     */
    public BootstrapClassLoader(File lib, ClassLoader parent) {
        super(new URL[0], parent);
        if (lib.isFile()) {
            throw new RuntimeException("lib must a dir " + lib);
        }
        this.addJarLib(lib);
    }

    /**
     * 添加一个jar库
     *
     * @param lib
     */
    public void addJarLib(File lib) {
        Set<File> files = new LinkedHashSet<>();
        listFiles(lib, files, new FileFilter() {
            @Override
            public boolean accept(File dir) {
                return dir.getName().endsWith(".jar");
            }
        });
        for (File f : files) {
            try {
                this.addURL(f.toURI().toURL());
            } catch (MalformedURLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 添加多个jar包
     *
     * @param urlSet
     * @throws IOException
     */
    public void addURLs(Set<URL> urlSet) throws IOException {
        for (URL url : urlSet) {
            addURL(url);
        }
    }

    protected void listFiles(File lib, Set<File> files, FileFilter filter) {
        lib.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.isDirectory()) {
                    listFiles(pathname, files, filter);
                } else {
                    if (filter.accept(pathname)) {
                        files.add(pathname);
                    }
                }
                return false;
            }
        });
    }
}
